//1.通过这个类 watcher  实现更新
import { pushTarget, popTarget } from "./dep";
import { nextTick } from "../utils/nextTick";
let id = 0;
class Watcher {
  constructor(vm, updataComponent, cb, options) {
    this.vm = vm;
    this.exprOrfn = updataComponent;
    this.cb = cb;
    this.options = options;
    this.user = !options.user;
    // this.getter = updataComponent;
    this.id = id++;
    this.deps = []; //watcher存放 dep
    this.depsId = new Set();
    // this.getter = vm._update(vm._render())
    //更新视图

    if (typeof this.exprOrfn === "function") {
      this.getter = this.exprOrfn;
    } else {
      this.get = function () {
        let path = this.exprOrfn.split(".");
        let obj = vm;
        for (let i = 0; i < path.length; i++) {
          obj = obj[path[i]];
        }
        return obj;
      };
    }
    this.value = this.get();
  }
  addDep(dep) {
    //1.去重
    let id = dep.id;
    if (!this.depsId.has(id)) {
      this.deps.push(dep);
      this.depsId.add = id;
      dep.addSub(this);
    }
  }
  run() {
    let value = this.get();
    console.log(value,'fds');
    let oldValue = this.value;
    this.value = value;
    console.log(value, oldValue);
    if (this.user) {
      this.cb.call(this.vm, value, oldValue);
    }
  }
  get() {
    pushTarget(this); //给dep添加 watcher
    this.getter(); //渲染
    popTarget(); // 给dep  取消watcher
  }
  updata() {
    // 注意：不要数据更新后每次都调用                缓存
    queueWatcher(this);
    // this.getter();
  }
}
let queue = []; //将需要批量更新的watcher  存放到一个列队中
let has = {};
function flushWatcher() {
  setTimeout(() => {
    queue.forEach((item) => {
      item.run(), item.cb();
    });
    queue = [];
    has = {};
  }, 0);
}
function queueWatcher(watcher) {
  let pending = false;
  let id = watcher.id;
  //防抖
  if (has[id] === undefined) {
    queue.push(watcher);
    has[id] = true;
    if (!pending) {
      nextTick(flushWatcher);
    }

    pending = true;
  }
}
export default Watcher;

//收集依赖，  Vue  dep  watcher  data：{name,age}
//dep 和 data中的属性是一一对应的。
//watcher  ：视图上用了几个，  就有几个watcher
// dep watcher 一对多
